package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisIdworker;
import com.hmdp.utils.UserHolder;
import com.hmdp.utils.simpleRedisLock;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */

/*
* todo 库存超卖问题
* 悲观锁
*  乐观锁
*todo 实现一人一单
*
* */
@Service



public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Autowired
    ISeckillVoucherService seckillVoucherService;

    @Autowired
    RedisIdworker redisIdworker;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public Result seckKillVoucher(Long voucherId) {
//        1.查询优惠券
        SeckillVoucher byId = seckillVoucherService.getById(voucherId);
//        2.判断秒杀是否开始
        if(byId.getBeginTime().isAfter(LocalDateTime.now())){
            return Result.fail("秒杀尚未开始");

        }

        if(byId.getEndTime().isBefore(LocalDateTime.now())){
            return Result.fail("秒杀已经结束");
        }
        if(byId.getStock()<1){
            return Result.fail("库存不足");
        }
        Long id = UserHolder.getUser().getId();

//       对于均衡负载分布式系统会出现锁失效的问题，故采用分布式锁的方式
//        synchronized (id.toString().intern()){
////            并非代理对像
//            IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();
//            return proxy.createVoucherOrder(voucherId);
//        }
        simpleRedisLock simpleRedisLock1 = new simpleRedisLock(stringRedisTemplate,"order"+id+voucherId);
        boolean IfLock = simpleRedisLock1.tryLock(3);
        if(!IfLock){
            return Result.fail("下单异常");
        }

        try {
           return  this.createVoucherOrder(voucherId);
        }finally {
            simpleRedisLock1.unlock();
        }


    }



//   此方法对于分布式系统无效
    @Transactional
//    这里使用事务的目的是防止中间流程终端时进行回退
    public  Result createVoucherOrder(Long voucherId) {
        Long id = UserHolder.getUser().getId();
//        失败率大大增加CAS法，乐观锁
//        返回字符串的规范表示

            boolean success = seckillVoucherService.update().setSql("stock=stock-1").eq("voucher_id", voucherId).gt("stock", 0).update();
            Integer count = query().eq("user_id", id).eq("voucher_id", voucherId).count();

            if (count > 0) {
                return Result.fail("该用户购买过了");
            }
            if (!success) {
                return Result.fail("库存不足");
            }


            VoucherOrder voucherOrder = new VoucherOrder();
            Long orderId = redisIdworker.nextID("order");

            voucherOrder.setId(orderId);
            voucherOrder.setVoucherId(voucherId);
            voucherOrder.setUserId(id);

            save(voucherOrder);

            return Result.ok(orderId);


    }
}
